package parking;

import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.MalformedURLException;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.Enumeration;
import java.util.List;

import parking.abcast.ABCast;
import parking.carvalho.Carvalho_Roucairol;
import parking.naimi_trehel.Naimi_Trehel;
import reso.Reso;

public class Door extends UnicastRemoteObject implements IDoor {

	private static final long serialVersionUID = 4851787099911828558L;
	private int identity;
	private IAlgorithm algo;
	private static final int NAIMI_TREHEL = 1;
	private static final int CARVALHO_ROUCAIROL = 2;
	private static final int ABCAST = 3;
	private CarManager carManager;

	public Door(int algorithmChoice, int nbSpots, Reso myReso) throws RemoteException {
		super();
		
		this.carManager = new CarManager(nbSpots);
		switch(algorithmChoice) {
		case NAIMI_TREHEL :
			this.algo = new Naimi_Trehel(this, nbSpots, myReso);
			break;
		case CARVALHO_ROUCAIROL :
			this.algo = new Carvalho_Roucairol(this, nbSpots, myReso);
			break;
		case ABCAST :
			this.algo = new ABCast(this, nbSpots, myReso, carManager);
			break;
		}
	}

	public int getIdentity() {
		return this.identity;
	}

	public void setIdentity(int identity) {
		this.identity = identity;
	}

	@Override
	public void demandeEntreeParking() throws RemoteException {
		this.algo.demandeEntree();
	}

	@Override
	public void demandeSortieParking() throws RemoteException {
		this.algo.demandeSortie();
	}

	private static String getHostname() throws SocketException {
		Enumeration<NetworkInterface> en =
				NetworkInterface.getNetworkInterfaces(); 
		while (en.hasMoreElements()){ 
			List<InterfaceAddress> i = en.nextElement().getInterfaceAddresses(); 
			for (InterfaceAddress l : i) {
				InetAddress addr = l.getAddress();
				if (addr.isSiteLocalAddress()){
					return addr.getHostAddress();
				}
			}
		}

		return "";
	}

	/**
	 * Server main program
	 * @param args : arg 0 - ip address of RMI registry, arg 1 - RMI port (default 1099), 
	 * 				 arg 2 - number of spots inside the parking, arg 3 - Algorithm numero
	 */
	public static void main(String[] args)  {		
		if (args.length < 4) {
			System.out.println("Il manque des arguments pour le bon fonctionnement du serveur de voitures");
			System.out.println("Usage : java Door <serveur> <port> <nbPlaces> <numAlgo>");
			System.out.println("(Algo :  1 pour Naimi Trehel, 2 pour Carvalho Roucairol, 3 pour ABCast)");
			return;
		}
		
		String serveur = args[0];
		int port = Integer.parseInt(args[1]);
		int nbPlaces = Integer.parseInt(args[2]);
		int algo = Integer.parseInt(args[3]);


		try {
			String hostname = getHostname();
			System.out.println("Found:" + hostname);
			System.setProperty("java.rmi.server.hostname", hostname);

			Reso myReso = (Reso) Naming.lookup("rmi://" + serveur + ":" + port + "/" + Reso.NAME);
			System.out.println("Objet distant RESO trouvé!");

			Door door = new Door(algo, nbPlaces, myReso);

			IServeurVoitures servV;

			servV = (IServeurVoitures) Naming.lookup("rmi://" + serveur + ":" + port + "/" + IServeurVoitures.NAME);

			System.out.println("Serveur de voitures trouvé");

			servV.enregistrerPorte(door);
			System.out.println("Porte enregistrée");

		} catch (MalformedURLException mue) {
			mue.printStackTrace();
		} catch (NotBoundException nbe) {
			nbe.printStackTrace();
		} catch (RemoteException re) {
			re.printStackTrace();
		} catch (SocketException se) {
			se.printStackTrace();
		}

	}

}
